package com.xbongbong.paas.service.workflow.setting.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.config.enums.WorkflowActionEnum;
import com.xbongbong.paas.config.enums.WorkflowTriggerMethodEnum;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.ProcessSaasFormEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.WorkflowHelp;
import com.xbongbong.paas.help.WorkflowNodeHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.workflow.WorkflowNodeTreePojo;
import com.xbongbong.paas.pojo.workflow.nodes.dto.WorkflowNodeBackDTO;
import com.xbongbong.paas.pojo.workflow.nodes.dto.WorkflowNodeCopyDTO;
import com.xbongbong.paas.pojo.workflow.nodes.dto.WorkflowNodeDeleteDTO;
import com.xbongbong.paas.pojo.workflow.nodes.dto.WorkflowNodeGetDTO;
import com.xbongbong.paas.pojo.workflow.nodes.dto.WorkflowNodeListDTO;
import com.xbongbong.paas.pojo.workflow.nodes.dto.WorkflowNodeSortDTO;
import com.xbongbong.paas.pojo.workflow.nodes.dto.WorkflowNodeSourceListDTO;
import com.xbongbong.paas.pojo.workflow.nodes.dto.WorkflowNodeUpdateDTO;
import com.xbongbong.paas.pojo.workflow.nodes.dto.WorkflowNodeViewDetailDTO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeBackVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeCopyVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeDeleteVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeGetVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeListVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeSaveVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeSortVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeSourceListVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeUpdateVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeViewDetailVO;
import com.xbongbong.paas.pojo.workflow.settings.ConditionTypeEnum;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowActionPoJo;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowGetPojo;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowNodeConditionTypeEnum;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowNodeListPoJo;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowNodeSaveDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.service.workflow.setting.WorkflowNodeService;
import com.xbongbong.paas.service.workflow.setting.WorkflowNodeSettings;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.WorkflowNodeUtil;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.enums.AccessLinkEnum;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ProErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.enums.workflow.TriggerEventTypeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderFormEntity;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.ext.WorkflowNodeEntityExt;
import com.xbongbong.workflow.enums.WorkflowNodeTypeEnum;
import com.xbongbong.workflow.model.WorkflowModel;
import com.xbongbong.workflow.model.WorkflowNodeModel;
import com.xbongbong.workflow.model.WorkflowTaskNodeModel;
import com.xbongbong.workflow.pojo.WorkflowNodeCoreConfiguration;
import com.xbongbong.workflow.pojo.nodes.ApprovalNode;
import com.xbongbong.workflow.pojo.nodes.ConditionNode;
import com.xbongbong.workflow.pojo.nodes.WorkflowJointConditionPojo;
import com.xbongbong.workflow.pojo.nodes.WorkflowNodePojo;
import com.xbongbong.workflow.pojo.nodes.WorkflowNodeSourceListPojo;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author 吴峰
 * @date 2021/05/10 10:24
 */
@Service("workFlowNodeServiceImpl")
public class WorkflowNodeServiceImpl implements WorkflowNodeService {


    private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowNodeServiceImpl.class);

    private static final String CONDITION_NODE_NAME = "constant.WorkflowNodeService.condition_node_name";

    private static final String NONE_RESULT_CONDITION_NODE_NAME = "constant.WorkflowNodeService.none_result_condition_node_name";

    private static final String APPROVAL_REFUSE_RESULT_CONDITION_NODE_NAME = "constant.WorkflowNodeService.approval_refuse_result_condition_node_name";

    @Resource
    private WorkflowNodeModel workflowNodeModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private Map<Integer, WorkflowNodeSettings> workflowNodeSettingsMap;
    @Resource
    private WorkflowModel workflowModel;
    @Resource
    private WorkflowNodeHelp workflowNodeHelp;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private WorkflowTaskNodeModel workflowTaskNodeModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private WorkflowHelp workflowHelp;
    @Resource
    private CommonHelp commonHelp;


    @Override
    public WorkflowNodeSaveVO save(WorkflowNodeSaveDTO workflowNodeSaveDTO) throws XbbException {
        WorkflowNodeSaveVO workflowNodeSaveVO = new WorkflowNodeSaveVO();
        String corpid = workflowNodeSaveDTO.getCorpid();
        Long workflowNodeId = workflowNodeSaveDTO.getWorkflowNodeId();
        Long workflowId = workflowNodeSaveDTO.getWorkflowId();

        //获取原工作流节点数（不包括条件块节点）
        Integer oldNodeCount =  workflowHelp.getNodeCount(corpid, workflowId);
        Integer maxCount = commonHelp.maxWorkflowNode(corpid);
        //执行操作前，判断节点数量是否超过上限
        if(Objects.isNull(workflowNodeId)){
            //新增节点
            if(Objects.equals(workflowNodeSaveDTO.getWorkflowNode().getType(),WorkflowNodeTypeEnum.CONDITION_NODE.getType())){
                //新增条件节点，会生成两个条件节点
                if( Objects.nonNull(workflowNodeSaveDTO.getMove()) && oldNodeCount + BasicConstant.TWO > maxCount){
                    throw new XbbException(ErrorCodeEnum.API_ERROR_260065, String.format(ErrorCodeEnum.API_ERROR_260065.getMsg(), maxCount));
                }
            }else{
                //新建非条件节点 或者追加一个条件，只会新增一个节点
                if(oldNodeCount >= maxCount){
                    throw new XbbException(ErrorCodeEnum.API_ERROR_260065, String.format(ErrorCodeEnum.API_ERROR_260065.getMsg(), maxCount));
                }
            }
        }else{
            //编辑节点
            if(oldNodeCount > maxCount){
                throw new XbbException(ErrorCodeEnum.API_ERROR_260065, String.format(ErrorCodeEnum.API_ERROR_260065.getMsg(), maxCount));
            }
        }
        // 并发锁
        String hashKey = corpid + StringConstant.UNDER_LINE + workflowNodeSaveDTO.getWorkflowId();
        try {
            ProPermissionHelp.verifyPermission(workflowNodeSaveDTO.getLoginUser(), ProPermissionAliasEnum.PROCESS_SET_UPDATE.getAlias());
            List<WorkflowNodeEntity> workflowNodeList;

            if (Objects.nonNull(paasRedisHelper.getValue(RedisPrefixConstant.WORKFLOW_SET, hashKey))) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260063);
            }
            // 加锁
            paasRedisHelper.setValue(RedisPrefixConstant.WORKFLOW_SET, hashKey, true, RedisConstant.MICRO_DURATION);

            if (Objects.isNull(workflowNodeId)) {

                // 新建逻辑
                WorkflowEntity workflowEntity = workflowModel.getByKey(workflowNodeSaveDTO.getWorkflowId(), corpid);
                if (Objects.equals(TriggerEventTypeEnum.ONLY_DELETE.getType(), workflowEntity.getTriggerEventType()) && WorkflowNodeTypeEnum.getApproveNodeList().contains(workflowNodeSaveDTO.getWorkflowNode().getType())){
                    throw new XbbException();
                }
                workflowNodeList = addWorkflowNode(corpid, workflowNodeSaveDTO.getType(), workflowNodeSaveDTO.getWorkflowId(),
                        workflowNodeSaveDTO.getWorkflowNode(), workflowNodeSaveDTO.getLoginUser(), workflowNodeSaveDTO.getHttpHeader(), workflowNodeSaveDTO.getMove());
                WorkflowNodeTreePojo workflowNodeTreePojo = getNodeTree(corpid, workflowNodeSaveDTO.getWorkflowId());
                workflowNodeSaveVO.setWorkflowNodeTree(workflowNodeTreePojo);
            } else {
                // 更新逻辑
                workflowNodeList = updateWorkflowNode(workflowNodeSaveDTO);
                List<Long> idIn = new ArrayList<>();
                workflowNodeList.forEach(item->{
                    idIn.add(item.getId());
                });
                workflowNodeList = workflowNodeModel.getByIdIn(idIn, corpid);
                WorkflowGetPojo workflowGetPojo = workflowNodeHelp.getContent(workflowNodeList, corpid);
                List<WorkflowNodeTreePojo> workflowNodeTreeList = workflowNodeHelp.getNodeList(workflowNodeList, workflowGetPojo);
                workflowNodeSaveVO.setWorkflowNodeTreeList(workflowNodeTreeList);
            }
            workflowNodeSaveVO.setWorkflowNodeList(workflowNodeList);
            // 解锁
            paasRedisHelper.removeValue(RedisPrefixConstant.WORKFLOW_SET, hashKey);
        } catch (XbbException e) {
            // 解锁
            paasRedisHelper.removeValue(RedisPrefixConstant.WORKFLOW_SET, hashKey);
            throw e;
        } catch (Exception e) {
            // 解锁
            paasRedisHelper.removeValue(RedisPrefixConstant.WORKFLOW_SET, hashKey);
            LOGGER.error("WorkflowSetServiceImpl.save error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowNodeSaveVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<WorkflowNodeEntity> addWorkflowNode(String corpid, Integer type, Long workflowId, WorkflowNodePojo workflowNodePojo, UserVO userVO, String httpHeader, Integer move) throws XbbException {
        try {
            String prevId = workflowNodePojo.getPrevId();
            WorkflowNodeEntity nextWorkflowNodeEntity = null;
            if (!Objects.equals(BasicConstant.ZERO.toString(), prevId)) {
                nextWorkflowNodeEntity = getNextNode(workflowId, prevId, corpid);
            }
            Long appId = workflowNodePojo.getAppId();
            Long menuId = workflowNodePojo.getMenuId();
            Long formId = workflowNodePojo.getFormId();
            Integer saasMark = workflowNodePojo.getSaasMark();
            Integer businessType = workflowNodePojo.getBusinessType();
            if (!Objects.equals(workflowNodePojo.getWrapperId(), workflowNodePojo.getPrevId()) && Objects.equals(WorkflowNodeTypeEnum.CONDITION_NODE.getType(), workflowNodePojo.getType())) {
                // 如果条件块节点为空，且新建的是条件节点，那么需要生成一个条件块节点，两个条件节点
                List<WorkflowNodeEntity> workflowNodeList = createConditionNode(corpid, type, workflowId, workflowNodePojo, userVO, httpHeader, move, nextWorkflowNodeEntity);
                return workflowNodeList;

            } else {
                boolean noApprove = (Objects.equals(WorkflowNodeTypeEnum.APPROVE_NODE.getType(), workflowNodePojo.getType()) || Objects.equals(WorkflowNodeTypeEnum.CC_NODE.getType(), workflowNodePojo.getType()))
                        && Objects.equals(saasMark, SaasMarkEnum.SAAS.getCode()) && !ProcessSaasFormEnum.workflowApproveNode(businessType);
                if (noApprove) {
                    // 无审批的节点
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.BUSINESS_TYPE_NOT_EXIST);
                }

                // 校验下一节点是否为审批节点，如果是审批节点则不允许起打开回退按钮
                validateApproveNodeHasBack(workflowNodePojo, nextWorkflowNodeEntity);

                WorkflowNodeEntity workflowNodeEntity = new WorkflowNodeEntity();
                workflowNodeEntity.setCorpid(corpid);
                workflowNodeEntity.setTriggerType(type);
                workflowNodeEntity.setType(workflowNodePojo.getType());
                String workflowNodeName = workflowNodePojo.getName();
                workflowNodeEntity.setName(workflowNodeName);
                workflowNodeEntity.setAppId(appId);
                workflowNodeEntity.setMenuId(menuId);
                workflowNodeEntity.setFormId(formId);
                workflowNodeEntity.setSaasMark(saasMark);
                workflowNodeEntity.setBusinessType(businessType);
                workflowNodeEntity.setWorkflowId(workflowId);
                workflowNodeEntity.setUid(workflowNodePojo.getNodeId());
                workflowNodeEntity.setPrevId(prevId);
                workflowNodeEntity.setPriority(workflowNodePojo.getPriority());
                workflowNodeEntity.setWrapperId(workflowNodePojo.getWrapperId());
                workflowNodeEntity.setConfigData(getConfigData(workflowNodePojo));
                // 节点插入
                workflowNodeModel.insert(workflowNodeEntity);
                String workflowMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_WORK), userVO.getName(), OperateModuleTypeEnum.WORKFLOW_TRIGGER_NODE.getName(), workflowNodeEntity.getName());
                mongoLogHelp.saveLoggerByInsert(corpid, userVO.getUserId(), userVO.getName(), workflowNodeEntity.getName(), workflowMemo, workflowNodeEntity.getId().toString(), httpHeader, OperateModuleTypeEnum.WORKFLOW_TRIGGER_NODE, OperateTypeEnum.NEW);

                if (Objects.nonNull(nextWorkflowNodeEntity) && !Objects.equals(WorkflowNodeTypeEnum.CONDITION_NODE.getType(), workflowNodePojo.getType())) {
                    // 更新下一节点的上一节点标识，新建条件节点时，不需要更新下一节点上一节点标识
                    WorkflowNodeEntity updateWorkflowNode = new WorkflowNodeEntity();
                    updateWorkflowNode.setId(nextWorkflowNodeEntity.getId());
                    updateWorkflowNode.setCorpid(corpid);
                    updateWorkflowNode.setPrevId(workflowNodeEntity.getUid());
                    updateWorkflowNode.setUpdateTime(DateTimeUtil.getInt());
                    workflowNodeModel.update(updateWorkflowNode);
                }
                if (Objects.equals(WorkflowNodeTypeEnum.APPROVE_NODE.getType(), workflowNodePojo.getType())) {
                    WorkflowEntity workflowEntity = new WorkflowEntity();
                    workflowEntity.setId(workflowId);
                    workflowEntity.setCorpid(corpid);
                    workflowEntity.setIsApprove(1);
                    workflowModel.update(workflowEntity);

                    // 设置流程标识
                    setProcessFlag(businessType, corpid, formId, 1);
                }
                List<WorkflowNodeEntity> workflowNodeList = new ArrayList<>();
                workflowNodeList.add(workflowNodeEntity);
                return workflowNodeList;
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.addWorkflowNode error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    private String getConfigData(WorkflowNodePojo workflowNodePojo) {
        WorkflowNodeCoreConfiguration workflowNodeCoreConfiguration = workflowNodePojo.getCoreConfiguration();
        if (Objects.equals(WorkflowNodeTypeEnum.START_NODE.getType(), workflowNodePojo.getType()) && Objects.nonNull(workflowNodeCoreConfiguration.getFormTriggerNode())) {
            return JSON.toJSONString(workflowNodeCoreConfiguration.getFormTriggerNode());
        } else if (Objects.equals(WorkflowNodeTypeEnum.CONDITION_NODE.getType(), workflowNodePojo.getType()) && Objects.nonNull(workflowNodeCoreConfiguration.getConditionNode())) {
            return JSON.toJSONString(workflowNodeCoreConfiguration.getConditionNode());
        } else if (Objects.equals(WorkflowNodeTypeEnum.APPROVE_NODE.getType(), workflowNodePojo.getType()) && Objects.nonNull(workflowNodeCoreConfiguration.getApprovalNode())) {
            return JSON.toJSONString(workflowNodeCoreConfiguration.getApprovalNode());
        } else if (Objects.equals(WorkflowNodeTypeEnum.CC_NODE.getType(), workflowNodePojo.getType()) && Objects.nonNull(workflowNodeCoreConfiguration.getCcNode())) {
            return JSON.toJSONString(workflowNodeCoreConfiguration.getCcNode());
        } else if (Objects.equals(WorkflowNodeTypeEnum.SINGLE_DATA_NODE.getType(), workflowNodePojo.getType()) && Objects.nonNull(workflowNodeCoreConfiguration.getObtainSingleDataNode())) {
            return JSON.toJSONString(workflowNodeCoreConfiguration.getObtainSingleDataNode());
        } else if (Objects.equals(WorkflowNodeTypeEnum.MULTI_DATA_NODE.getType(), workflowNodePojo.getType()) && Objects.nonNull(workflowNodeCoreConfiguration.getObtainMultiDataNode())) {
            return JSON.toJSONString(workflowNodeCoreConfiguration.getObtainMultiDataNode());
        }else if (Objects.equals(WorkflowNodeTypeEnum.CREATE_NODE.getType(), workflowNodePojo.getType()) && Objects.nonNull(workflowNodeCoreConfiguration.getInsertRecordNode())) {
            return JSON.toJSONString(workflowNodeCoreConfiguration.getInsertRecordNode());
        }else if (Objects.equals(WorkflowNodeTypeEnum.SEND_MESSAGE_NODE.getType(), workflowNodePojo.getType()) && Objects.nonNull(workflowNodeCoreConfiguration.getSendMsgNode())) {
            return JSON.toJSONString(workflowNodeCoreConfiguration.getSendMsgNode());
        }else if (Objects.equals(WorkflowNodeTypeEnum.DELETE_NODE.getType(), workflowNodePojo.getType()) && Objects.nonNull(workflowNodeCoreConfiguration.getDeleteRecordNode())) {
            return JSON.toJSONString(workflowNodeCoreConfiguration.getDeleteRecordNode());
        }else if (Objects.equals(WorkflowNodeTypeEnum.UPDATE_NODE.getType(), workflowNodePojo.getType()) && Objects.nonNull(workflowNodeCoreConfiguration.getUpdateRecordNode())) {
            return JSON.toJSONString(workflowNodeCoreConfiguration.getUpdateRecordNode());
        }
        return JSON.toJSONString(new JSONObject());
    }

    /**
     * 删除节点时，校验该节点下是否存在节点任务
     * @param corpid
     * @param nodeIdList
     * @throws XbbException
     */
    private void validateNodeTask(String corpid, Collection<Long> nodeIdList) throws XbbException {
        if (CollectionsUtil.isEmpty(nodeIdList)) {
            return;
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("workflowNodeIdIn", nodeIdList);
        Integer count = workflowTaskNodeModel.getEntityCount(param);
        if (count > 0) {
            throw new XbbException(ProErrorCodeEnum.API_ERROR_260044);
        }
    }

    /**
     * 设置流程标识
     * @param businessType
     * @param corpid
     * @param formId
     * @param isProcessForm
     * @throws XbbException
     */
    private void setProcessFlag(Integer businessType, String corpid, Long formId, Integer isProcessForm) throws XbbException{
        if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), businessType)) {
            WorkOrderFormEntity workOrderFormEntity = new WorkOrderFormEntity();
            workOrderFormEntity.setId(formId);
            workOrderFormEntity.setCorpid(corpid);
            workOrderFormEntity.setIsProcessForm(isProcessForm);
            workOrderFormEntity.setUpdateTime(DateTimeUtil.getInt());
            workOrderFormModel.update(workOrderFormEntity);
        } else {
            PaasFormEntity paasFormEntity = new PaasFormEntity();
            paasFormEntity.setId(formId);
            paasFormEntity.setCorpid(corpid);
            paasFormEntity.setIsProcessForm(isProcessForm);
            paasFormEntity.setUpdateTime(DateTimeUtil.getInt());
            paasFormModel.update(paasFormEntity);
        }
    }

    /**
     * 校验下一节点是否为审批节点，如果是审批节点则不允许起打开回退按钮
     * @param workflowNodePojo
     * @param nextNode
     * @throws XbbException
     */
    private void validateApproveNodeHasBack(WorkflowNodePojo workflowNodePojo, WorkflowNodeEntity nextNode) throws XbbException{
        if (WorkflowNodeTypeEnum.getDataProcessingNodeList().contains(workflowNodePojo.getType()) && Objects.nonNull(nextNode)) {
            if (Objects.equals(nextNode.getType(), WorkflowNodeTypeEnum.CONDITION_BLOCK_NODE.getType())) {
                // 麻了麻了，判断条件块里的条件下一节点是否为审批节点，如果是审批节点则不允许起打开回退按钮
                validateApproveNodeBack(nextNode);
            } else if (Objects.equals(WorkflowNodeTypeEnum.APPROVE_NODE.getType(), nextNode.getType())){
                ApprovalNode approvalNode = JSON.parseObject(nextNode.getConfigData(), ApprovalNode.class);
                if (Objects.nonNull(approvalNode) && Objects.equals(approvalNode.getBackFlag(), 1)) {
                    throw new XbbException(ProErrorCodeEnum.API_ERROR_260040, ProErrorCodeEnum.API_ERROR_260040.getMsg(), nextNode.getName());
                }
            }
        }
    }

    /**
     * 判断条件块里的条件下一节点是否为审批节点，如果是审批节点则不允许起打开回退按钮
     * @param nextNode
     * @throws XbbException
     */
    private void validateApproveNodeBack(WorkflowNodeEntity nextNode) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, nextNode.getCorpid());
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("workflowId", nextNode.getWorkflowId());
        param.put("wrapperId", nextNode.getUid());
        List<WorkflowNodeEntity> list = workflowNodeModel.findEntitys(param);
        if (CollectionUtils.isNotEmpty(list)) {
            List<String> uidList = new ArrayList<>();
            list.forEach(item->uidList.add(item.getUid()));
            param.clear();
            param.put(StringConstant.CORPID, nextNode.getCorpid());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("prevIdIn", uidList);
            param.put("orderByStr", "type ASC");
            list = workflowNodeModel.findEntitys(param);
            for (WorkflowNodeEntity item : list) {
                if (Objects.equals(WorkflowNodeTypeEnum.APPROVE_NODE.getType(), item.getType())) {
                    ApprovalNode approvalNode = JSON.parseObject(item.getConfigData(), ApprovalNode.class);
                    if (Objects.nonNull(approvalNode) && Objects.equals(approvalNode.getBackFlag(), 1)) {
                        throw new XbbException(ProErrorCodeEnum.API_ERROR_260040, ProErrorCodeEnum.API_ERROR_260040.getMsg(), item.getName());
                    }
                } else if (Objects.equals(WorkflowNodeTypeEnum.CONDITION_BLOCK_NODE.getType(), item.getType())){
                    validateApproveNodeBack(item);
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WorkflowNodeDeleteVO delete(WorkflowNodeDeleteDTO workflowNodeDeleteDTO) throws XbbException {
        WorkflowNodeDeleteVO workflowNodeDeleteVO = new WorkflowNodeDeleteVO();
        String corpid = workflowNodeDeleteDTO.getCorpid();
        Long workflowNodeId = workflowNodeDeleteDTO.getWorkflowNodeId();
        WorkflowNodeEntity workflowNodeEntity =  workflowNodeModel.getByKey(workflowNodeId, corpid);
        if (Objects.isNull(workflowNodeEntity)) {
            throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
        }
        // 并发锁
        String hashKey = corpid + StringConstant.UNDER_LINE + workflowNodeEntity.getWorkflowId();
        if (Objects.nonNull(paasRedisHelper.getValue(RedisPrefixConstant.WORKFLOW_SET, hashKey))) {
            throw new XbbException(ProErrorCodeEnum.API_ERROR_260063);
        }
        try {
            ProPermissionHelp.verifyPermission(workflowNodeDeleteDTO.getLoginUser(), ProPermissionAliasEnum.PROCESS_SET_UPDATE.getAlias());
            // 加锁
            paasRedisHelper.setValue(RedisPrefixConstant.WORKFLOW_SET, hashKey, true, RedisConstant.MICRO_DURATION);

            WorkflowNodeEntity nextWorkflowNode = null;
            WorkflowNodeEntity updateWorkflowNode = new WorkflowNodeEntity();
            String prevId = workflowNodeEntity.getPrevId();
            Long workflowId = workflowNodeEntity.getWorkflowId();
            if (Objects.equals(workflowNodeEntity.getType(), WorkflowNodeTypeEnum.CONDITION_NODE.getType())) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID, corpid);
                param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                param.put("wrapperId", workflowNodeEntity.getWrapperId());
                param.put("type", WorkflowNodeTypeEnum.CONDITION_NODE.getType());
                param.put("workflowId", workflowId);
                List<WorkflowNodeEntity> list = workflowNodeModel.findEntitys(param);
                if (list.size() == BasicConstant.TWO) {
                    // 只剩两个条件节点（条件1，条件2，如果删除的是条件1），那么需要判断两个节点下是否都含有节点；
                    // 1. 如果另外一个节点（条件2）下含有节点，需要删掉两个节点以及块节点，但是不可以删除另外一个节点（条件2）下面的节点， 需要将其下方的节点放入工作流，即将其下方的节点的prevId改为wrapperNode的prevId，如果该条件块下方存在节点，则需要找到另外一个节点（条件2）下方的最后一个节点，将条件块下方的节点的prev_id改为条件2最后一节点的uid
                    // 2. 如果另外一个节点下不含有节点，则删除两个节点、块节点以及下面的节点， 再将wrapperNode下方的节点的prevId改为wrapperNode的prevId

                    WorkflowNodeEntity wrapperNode = workflowNodeModel.getByUId(workflowId, corpid, workflowNodeEntity.getWrapperId());
                    prevId = wrapperNode.getPrevId();
                    WorkflowNodeEntity otherConditionNode = null;
                    List<Long> deleteList = new ArrayList<>();
                    for (WorkflowNodeEntity item : list) {
                        // 删除两个条件节点
                        deleteList.add(item.getId());
                        if (!Objects.equals(item.getId(), workflowNodeId)) {
                            // 获取非本节点的另一个节点，需要判断这个节点有没有下属节点
                            otherConditionNode = item;
                        }
                    }
                    // 删除块节点
                    deleteList.add(wrapperNode.getId());
                    WorkflowNodeEntity firstNode = null;
                    if (Objects.nonNull(otherConditionNode)) {
                        List<WorkflowNodeEntity> otherList = workflowNodeModel.getByWrapperId(otherConditionNode.getWrapperId(), corpid, workflowId);
                        if (CollectionUtils.isNotEmpty(otherList)) {
                            // 拿到条件下的第一个节点，需要将这个节点的prevId改成块节点的prevId
                            firstNode = WorkflowNodeUtil.getFirstNode(otherList, otherConditionNode.getUid());
                            if (Objects.nonNull(firstNode)) {
                                // 拿到另一个条件下的最后一个节点，如果最后一个节点是块节点，则拿块节点，将块节点的下一个节点的prevId改成这个节点的uid
                                WorkflowNodeEntity lastNode = WorkflowNodeUtil.getLastNode(otherList, otherConditionNode.getUid());
                                if (Objects.nonNull(lastNode)) {
                                    prevId = lastNode.getUid();
                                }
                            }

                        }
                        // 获取用户指定节点的下方所有的节点
                        deleteList.addAll(getDeleteList(corpid, workflowId, workflowNodeEntity));
                    } else {
                        // 获取用户指定节点的所在块节点下方所有的节点
                        deleteList.addAll(getDeleteList(corpid, workflowId, wrapperNode));
                    }

                    // 对删除的节点进行校验，判断是否存在节点任务
                    validateNodeTask(corpid, deleteList);
                    if (CollectionsUtil.isNotEmpty(deleteList)) {
                        workflowNodeModel.deleteBatch(deleteList, corpid);
                    }
                    if (Objects.nonNull(otherConditionNode)) {
                        List<Long> idIn = new ArrayList<>();
                        List<WorkflowNodeEntity> wrapperNodeList = workflowNodeModel.getByWrapperId(wrapperNode.getUid(), corpid, workflowId);
                        if (CollectionUtils.isNotEmpty(wrapperNodeList)) {
                            wrapperNodeList.forEach(item->idIn.add(item.getId()));
                            workflowNodeModel.updateWrapperIdByIdIn(idIn, wrapperNode.getWrapperId(), corpid);
                        }
                    }
                    nextWorkflowNode = getNextNode(workflowId, wrapperNode.getUid(), corpid);
                    // 删除节点后，则更新下一个节点的prevId
                    // 当删除的是最后一个节点时，那么获取不到下一个节点，所以这里加个null判断
                    if (Objects.nonNull(nextWorkflowNode) || Objects.nonNull(firstNode)) {
                        List<WorkflowNodeEntity> updateList = new ArrayList<>();
                        long now = DateTimeUtil.getInt();
                        if (Objects.nonNull(nextWorkflowNode)) {
                            updateWorkflowNode.setId(nextWorkflowNode.getId());
                            updateWorkflowNode.setCorpid(corpid);
                            updateWorkflowNode.setPrevId(prevId);
                            updateWorkflowNode.setUpdateTime(now);
                            updateList.add(updateWorkflowNode);
                        }
                        if (Objects.nonNull(firstNode)) {
                            updateWorkflowNode = new WorkflowNodeEntity();
                            updateWorkflowNode.setId(firstNode.getId());
                            updateWorkflowNode.setCorpid(corpid);
                            updateWorkflowNode.setPrevId(wrapperNode.getPrevId());
                            updateWorkflowNode.setUpdateTime(now);
                            updateList.add(updateWorkflowNode);
                        }
                        workflowNodeModel.updatePrevIdBatch(updateList, corpid);
                    }
                } else {
                    // 如果还剩两个（不包括两个）以上的条件节点
                    Set<Long> deleteList = getDeleteList(corpid, workflowId, workflowNodeEntity);
                    List<WorkflowNodeEntity> sortPriorityList = new ArrayList<>();
                    long now = DateTimeUtil.getInt();
                    list.forEach(item->{
                        if (!Objects.equals(item.getId(), workflowNodeEntity.getId()) && item.getPriority() > workflowNodeEntity.getPriority()) {
                            // 删除条件分支节点时，对大于当前删除的节点的优先级进行重排序；
                            WorkflowNodeEntity sortNode = new WorkflowNodeEntity();
                            Integer priority = item.getPriority();
                            priority--;
                            sortNode.setUpdateTime(now);
                            sortNode.setPriority(priority);
                            sortNode.setId(item.getId());
                            sortPriorityList.add(sortNode);
                        }
                     });

                    deleteList.add(workflowNodeId);
                    // 对删除的节点进行校验，判断是否存在节点任务
                    validateNodeTask(corpid, deleteList);
                    if (CollectionsUtil.isNotEmpty(deleteList)) {
                        workflowNodeModel.deleteBatch(deleteList, corpid);
                        if (CollectionsUtil.isNotEmpty(sortPriorityList)) {
                            workflowNodeModel.sort(sortPriorityList, corpid);
                        }
                    }
                }

            } else {
                // 对删除的节点进行校验，判断是否存在节点任务
                validateNodeTask(corpid, Collections.singletonList(workflowNodeId));
                workflowNodeModel.deleteByKey(workflowNodeId, corpid);
                // 对其他节点进行逻辑处理；
                nextWorkflowNode = getNextNode(workflowId, workflowNodeEntity.getUid(), corpid);
                // 删除节点后，则更新下一个节点的prevId
                // 当删除的是最后一个节点时，那么获取不到下一个节点，所以这里加个null判断
                if (Objects.nonNull(nextWorkflowNode)) {
                    updateWorkflowNode.setId(nextWorkflowNode.getId());
                    updateWorkflowNode.setCorpid(corpid);
                    updateWorkflowNode.setPrevId(prevId);
                    workflowNodeModel.update(updateWorkflowNode);
                }
            }

            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("workflowId", workflowNodeEntity.getWorkflowId());
            param.put("type", WorkflowNodeTypeEnum.APPROVE_NODE.getType());
            Integer count = workflowNodeModel.getEntitysCount(param);
            if (count == 0) {
                // 如果没有了审批节点，则需要改审批标识更改掉
                WorkflowEntity workflowEntity = new WorkflowEntity();
                workflowEntity.setId(workflowNodeEntity.getWorkflowId());
                workflowEntity.setCorpid(corpid);
                workflowEntity.setIsApprove(0);
                workflowModel.update(workflowEntity);

                // 设置流程标识
                setProcessFlag(workflowNodeEntity.getBusinessType(), corpid, workflowNodeEntity.getFormId(), 0);
            }
            WorkflowNodeTreePojo workflowNodeTreePojo = getNodeTree(corpid, workflowId);
            workflowNodeDeleteVO.setWorkflowNodeTree(workflowNodeTreePojo);
            // 解锁
            paasRedisHelper.removeValue(RedisPrefixConstant.WORKFLOW_SET, hashKey);
        } catch (XbbException e) {
            // 解锁
            paasRedisHelper.removeValue(RedisPrefixConstant.WORKFLOW_SET, hashKey);
            throw e;
        }catch (Exception e) {
            // 解锁
            paasRedisHelper.removeValue(RedisPrefixConstant.WORKFLOW_SET, hashKey);
            LOGGER.error("WorkflowSetServiceImpl.delete error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowNodeDeleteVO;
    }

    @Override
    public WorkflowNodeListVO list(WorkflowNodeListDTO workflowNodeListDTO) throws XbbException{

        List<WorkflowActionPoJo> actionList = new ArrayList<>();
        Integer feeType = packageHelp.getFeeType(workflowNodeListDTO.getCorpid());
        boolean standard = Objects.equals(PackageTypeEnum.ULTIMATE.getType(), feeType);
        for (WorkflowActionEnum workflowActionEnum: WorkflowActionEnum.values()) {

            if (Objects.equals(workflowActionEnum.getType(), WorkflowActionEnum.DATA_PROCESSING.getType()) && !standard) {
                // 标准版、高级版不可以用这个
                continue;
            }
            List<WorkflowNodeListPoJo> nodeActionList = new ArrayList<>();
            List<WorkflowNodeTypeEnum> nodeList = workflowActionEnum.getNodeList();

            // 自定义工作流人工节点只有发消息节点
            if (Objects.equals(workflowNodeListDTO.getType(), WorkflowTriggerMethodEnum.CUSTOM_TRIGGER_METHOD.getType()) && Objects.equals(workflowActionEnum.getType(), WorkflowActionEnum.ARTIFICIAL_NODE.getType())) {
                nodeList = nodeList.stream().filter(v -> v.equals(WorkflowNodeTypeEnum.SEND_MESSAGE_NODE)).collect(Collectors.toList());
            }

            nodeList.forEach(item->{
                if (Objects.equals(item.getType(), WorkflowNodeTypeEnum.SEND_MESSAGE_NODE.getType()) && !standard) {
                    // 标准版、高级版不可以用这个
                    return;
                }
                AccessLinkEnum accessLinkEnum = item.getAccessLinkEnum();
                WorkflowNodeListPoJo workflowNodeListPoJo = new WorkflowNodeListPoJo(item.getMemo(), accessLinkEnum.getColor(), item.getType(), accessLinkEnum.getIcon());
                nodeActionList.add(workflowNodeListPoJo);
            });
            WorkflowActionPoJo workflowActionPoJo = new WorkflowActionPoJo(workflowActionEnum.getDesc(), workflowActionEnum.getType(), nodeActionList);
            actionList.add(workflowActionPoJo);
        }
        WorkflowNodeListVO workflowNodeListVO = new WorkflowNodeListVO();
        workflowNodeListVO.setActionList(actionList);
        return workflowNodeListVO;
    }


    @Override
    public WorkflowNodeGetVO get(WorkflowNodeGetDTO workflowNodeGetDTO) throws XbbException {
        try {
            Long workflowNodeId = workflowNodeGetDTO.getWorkflowNodeId();
            String corpid = workflowNodeGetDTO.getCorpid();
            Long workflowId = workflowNodeGetDTO.getWorkflowId();
            WorkflowEntity workflowEntity =  workflowModel.getByKey(workflowId, corpid);
            if (Objects.isNull(workflowEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
            }
            WorkflowNodeEntity workflowNodeEntity =  workflowNodeModel.getByKey(workflowNodeId, corpid);
            if (Objects.isNull(workflowNodeEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
            }
            WorkflowNodeSettings workflowNodeSettings = workflowNodeSettingsMap.get(workflowNodeEntity.getType());
            WorkflowNodeGetVO workflowNodeGetVO = workflowNodeSettings.get(workflowNodeEntity);
            workflowNodeGetVO.setUsePermission(workflowEntity.getUsePermission());
            workflowNodeGetVO.setName(workflowNodeEntity.getName());
            workflowNodeGetVO.setType(workflowNodeEntity.getType());
            workflowNodeGetVO.setTriggerType(workflowEntity.getTriggerEventType());
            workflowNodeGetVO.setWorkflowType(workflowEntity.getType());
            workflowNodeGetVO.setWorkflowId(workflowEntity.getId());
            return workflowNodeGetVO;
        } catch (XbbException e) {
            throw e;
        }catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.get error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }


    @Override
    public WorkflowNodeSortVO sort(WorkflowNodeSortDTO workflowNodeSortDTO) throws XbbException {
        try {

            List<WorkflowNodeEntity> list = new ArrayList<>();
            Integer sort = 1;
            for (Long item : workflowNodeSortDTO.getWorkflowNodeId()) {
                WorkflowNodeEntity workflowEntity = new WorkflowNodeEntity();
                workflowEntity.setId(item);
                workflowEntity.setPriority(sort);
                workflowEntity.setUpdateTime(DateTimeUtil.getInt());
                sort++;
                list.add(workflowEntity);

            }
            workflowNodeModel.sort(list, workflowNodeSortDTO.getCorpid());
            String corpid = workflowNodeSortDTO.getCorpid();
            WorkflowNodeTreePojo workflowNodeTreePojo = getNodeTree(corpid, workflowNodeSortDTO.getWorkflowId());

            return new WorkflowNodeSortVO(workflowNodeTreePojo);

        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.sort error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public WorkflowNodeSourceListVO sourceNodeList(WorkflowNodeSourceListDTO workflowNodeSourceListDTO) throws XbbException {
        try {
            WorkflowNodeSourceListVO workflowNodeSourceListVO = new WorkflowNodeSourceListVO();
            String corpid = workflowNodeSourceListDTO.getCorpid();
            Long workflowId = workflowNodeSourceListDTO.getWorkflowId();
            String prevId = workflowNodeSourceListDTO.getNodeId();
            List<Integer> nodeList = Arrays.asList(WorkflowNodeTypeEnum.MULTI_DATA_NODE.getType());
            List<WorkflowNodeSourceListPojo> sourceList = getNodeList(corpid, prevId, workflowId, nodeList);
            workflowNodeSourceListVO.setSourceList(sourceList);
            return workflowNodeSourceListVO;
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.sourceNodeList error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }


    @Override
    public WorkflowNodeUpdateVO update(WorkflowNodeUpdateDTO workflowNodeUpdateDTO) throws XbbException {
        WorkflowNodeUpdateVO workflowNodeUpdateVO = new WorkflowNodeUpdateVO();
        try {
            ProPermissionHelp.verifyPermission(workflowNodeUpdateDTO.getLoginUser(), ProPermissionAliasEnum.PROCESS_SET_UPDATE.getAlias());

            Long workflowNodeId = workflowNodeUpdateDTO.getWorkflowNodeId();
            String corpid = workflowNodeUpdateDTO.getCorpid();

            WorkflowNodeEntity workflowNodeEntity =  workflowNodeModel.getByKey(workflowNodeId, corpid);
            if (Objects.isNull(workflowNodeEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
            }
            WorkflowNodeEntity result = new WorkflowNodeEntity();
            result.setId(workflowNodeId);
            result.setCorpid(corpid);
            result.setMemo(workflowNodeUpdateDTO.getMemo());
            result.setName(workflowNodeUpdateDTO.getName());
            result.setUpdateTime(DateTimeUtil.getInt());
            workflowNodeModel.update(result);
            workflowNodeUpdateVO.setMemo(workflowNodeUpdateDTO.getMemo());
            workflowNodeUpdateVO.setName(workflowNodeUpdateDTO.getName());
            workflowNodeUpdateVO.setWorkflowNodeId(workflowNodeId);
        }  catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.updateMemo error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowNodeUpdateVO;
    }

    @Override
    public WorkflowNodeBackVO back(WorkflowNodeBackDTO workflowNodeBackDTO) throws XbbException {
        WorkflowNodeBackVO workflowNodeBackVO = new WorkflowNodeBackVO();
        try {
            if (!workflowNodeBackDTO.getEnable()) {
                // 关闭回退按钮无需校验
                workflowNodeBackVO.setEnable(true);
                return workflowNodeBackVO;
            }
            Long workflowNodeId = workflowNodeBackDTO.getWorkflowNodeId();
            String corpid = workflowNodeBackDTO.getCorpid();
            WorkflowNodeEntity workflowNodeEntity =  workflowNodeModel.getByKey(workflowNodeId, corpid);
            if (Objects.isNull(workflowNodeEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
            }
            // 获取上一个的节点
            WorkflowNodeEntity lastNode = workflowNodeHelp.findLastNode(workflowNodeEntity);
            if (workflowNodeBackDTO.getEnable() && Objects.nonNull(lastNode)
                    && WorkflowNodeTypeEnum.getDataProcessingNodeList().contains(lastNode.getType())) {
                // 如果回退按钮开启之后，其上一节点如果是数据处理节点，则不允许开启该按钮；
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260039, ProErrorCodeEnum.API_ERROR_260039.getMsg(), workflowNodeEntity.getName());
            }
            workflowNodeBackVO.setEnable(true);
            return workflowNodeBackVO;
        } catch (XbbException e) {
            throw e;
        }  catch (Exception e) {
            LOGGER.error("WorkflowNodeServiceImpl.revoke error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public WorkflowNodeCopyVO copy(WorkflowNodeCopyDTO workflowNodeCopyDTO) throws XbbException {
        WorkflowNodeCopyVO workflowNodeCopyVO = new WorkflowNodeCopyVO();
        try {
            Long workflowNodeId = workflowNodeCopyDTO.getWorkflowNodeId();
            String corpid = workflowNodeCopyDTO.getCorpid();
            WorkflowNodeEntity workflowNodeEntity =  workflowNodeModel.getByKey(workflowNodeId, corpid);
            if (Objects.isNull(workflowNodeEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
            }
            //兼容老数据
            WorkflowJointConditionPojo conditions = workflowNodeHelp.getConditionNode(workflowNodeEntity).getConditions();
            JSONObject config = JSONObject.parseObject(workflowNodeEntity.getConfigData());
            config.put("conditions", conditions);
            workflowNodeEntity.setConfigData(config.toJSONString());

            // 校验条件节点else属性
            WorkflowNodePojo workflowNodePojo = new WorkflowNodePojo();
            workflowNodePojo.setType(workflowNodeEntity.getType());
            WorkflowNodeCoreConfiguration workflowNodeCoreConfiguration = new WorkflowNodeCoreConfiguration();
            ConditionNode conditionNode = JSON.parseObject(workflowNodeEntity.getConfigData(), ConditionNode.class);
            workflowNodeCoreConfiguration.setConditionNode(conditionNode);
            workflowNodePojo.setCoreConfiguration(workflowNodeCoreConfiguration);
            validateElse(workflowNodePojo, corpid, workflowNodeEntity.getWorkflowId(), null);

            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("workflowId", workflowNodeEntity.getWorkflowId());
            List<WorkflowNodeEntity> workflowNodeEntityList = workflowNodeModel.findEntitys(param);
            String wrapperId = workflowNodeEntity.getWrapperId();
            String prevId = workflowNodeEntity.getPrevId();
            if(CollectionUtils.isEmpty(workflowNodeEntityList)){
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260036, ProErrorCodeEnum.API_ERROR_260036.getMsg());
            }
            Set<WorkflowNodeEntity> conditionNodeList = workflowNodeEntityList.stream()
                    .filter(v -> Objects.equals(v.getWrapperId(), wrapperId) && Objects.equals(v.getPrevId(), prevId) &&  Objects.equals(v.getType(), WorkflowNodeTypeEnum.CONDITION_NODE.getType()))
                    .collect(Collectors.toSet());
            Integer sort = conditionNodeList.size();
            workflowNodeEntity.setId(null);
            workflowNodeEntity.setName(workflowNodeEntity.getName() + StringConstant.UNDER_LINE + I18nMessageUtil.getMessage(CommonConstant.COPY));
            workflowNodeEntity.setUid(UUID.randomUUID().toString());
            sort++;
            workflowNodeEntity.setPriority(sort);
            long now = DateTimeUtil.getInt();
            workflowNodeEntity.setAddTime(now);
            workflowNodeEntity.setUpdateTime(now);
            //节点数量限制
            long count = workflowNodeEntityList.stream()
                    .filter(v -> !Objects.equals(WorkflowNodeTypeEnum.CONDITION_BLOCK_NODE.getType(), v.getType()))
                    .count();
            Integer maxCount = commonHelp.maxWorkflowNode(corpid);
            if(count + 1 > maxCount){
                throw new XbbException(ErrorCodeEnum.API_ERROR_260065, String.format(ErrorCodeEnum.API_ERROR_260065.getMsg(), maxCount));
            }
            workflowNodeModel.insert(workflowNodeEntity);

            WorkflowNodeTreePojo workflowNodeTreePojo = getNodeTree(corpid, workflowNodeEntity.getWorkflowId());
            workflowNodeCopyVO.setWorkflowNodeTreePojo(workflowNodeTreePojo);
            return workflowNodeCopyVO;
        } catch (XbbException e) {
            throw e;
        }  catch (Exception e) {
            LOGGER.error("WorkflowNodeServiceImpl.copy error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * 复制某个条件分支下面的所有节点
     *
     * @param workflowNodeCopyDTO
     * @return
     * @throws XbbException
     */
    @Override
    public WorkflowNodeCopyVO copyAllNode(WorkflowNodeCopyDTO workflowNodeCopyDTO) throws XbbException {
        WorkflowNodeCopyVO workflowNodeCopyVO = new WorkflowNodeCopyVO();
        try {
            Long workflowNodeId = workflowNodeCopyDTO.getWorkflowNodeId();
            String corpid = workflowNodeCopyDTO.getCorpid();
            WorkflowNodeEntityExt workflowNodeEntity =  workflowNodeModel.getExtByKey(workflowNodeId, corpid);
            if (Objects.isNull(workflowNodeEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
            }
            //兼容老数据
            WorkflowJointConditionPojo conditions = workflowNodeHelp.getConditionNode(workflowNodeEntity).getConditions();
            JSONObject config = JSONObject.parseObject(workflowNodeEntity.getConfigData());
            config.put("conditions", conditions);
            workflowNodeEntity.setConfigData(config.toJSONString());

            // 校验条件节点else属性
            WorkflowNodePojo workflowNodePojo = new WorkflowNodePojo();
            workflowNodePojo.setType(workflowNodeEntity.getType());
            WorkflowNodeCoreConfiguration workflowNodeCoreConfiguration = new WorkflowNodeCoreConfiguration();
            ConditionNode conditionNode = JSON.parseObject(workflowNodeEntity.getConfigData(), ConditionNode.class);
            workflowNodeCoreConfiguration.setConditionNode(conditionNode);
            workflowNodePojo.setCoreConfiguration(workflowNodeCoreConfiguration);
            validateElse(workflowNodePojo, corpid, workflowNodeEntity.getWorkflowId(), null);
            //复制条件分支下的所有节点，目前通过递归去做，找出每一个之后需要重新赋值
            Map<String, Object> workflowParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            workflowParam.put(ParameterConstant.CORPID, corpid);
            workflowParam.put("workflowId", workflowNodeEntity.getWorkflowId());
            workflowParam.put(ParameterConstant.ORDER_BY_STR, "priority");
            workflowParam.put(StringConstant.DEL, BasicConstant.ZERO);
            List<WorkflowNodeEntity> nodeList = workflowNodeModel.findEntitys(workflowParam);
            // 获取需要复制的节点
            List<WorkflowNodeEntity> copyAllList = getAnyNodeUnderAllNodeList(nodeList, workflowNodeEntity );

            Integer maxCount = commonHelp.maxWorkflowNode(corpid);
            //这边还需要校验一下不能超过100个节点
            if (CollectionsUtil.isNotEmpty(nodeList)) {
                long nodeNoConditionBlockListCount = nodeList.stream()
                        .filter(workflowNodeEntityExt -> !Objects.equals(WorkflowNodeTypeEnum.CONDITION_BLOCK_NODE.getType(), workflowNodeEntityExt.getType()))
                        .count();
                long copyNodeNoConditionBlockListCount = copyAllList.stream()
                        .filter(workflowNodeEntityExt -> !Objects.equals(WorkflowNodeTypeEnum.CONDITION_BLOCK_NODE.getType(), workflowNodeEntityExt.getType()))
                        .count();
                if (nodeNoConditionBlockListCount + copyNodeNoConditionBlockListCount > maxCount) {
                    throw new XbbException(ErrorCodeEnum.API_ERROR_260065, String.format(ErrorCodeEnum.API_ERROR_260065.getMsg(), maxCount));
                }
            }
            if (CollectionsUtil.isNotEmpty(copyAllList)) {
                workflowNodeModel.insertBatch(copyAllList);
            }
            WorkflowNodeTreePojo workflowNodeTreePojo = getNodeTree(corpid, workflowNodeEntity.getWorkflowId());
            workflowNodeCopyVO.setWorkflowNodeTreePojo(workflowNodeTreePojo);
            return workflowNodeCopyVO;
        } catch (XbbException e) {
            throw e;
        }  catch (Exception e) {
            LOGGER.error("WorkflowNodeServiceImpl.copyAllNode error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }


    /**
     *
     * 根据某个条件分支节点的uuid，去获取这个节点下面的所有节点,这个方法只给分支复制方法使用
     * 不是深拷贝
     * @param nodeList
     * @param workflowNodeEntity 需要开始查询的节点
     * @return
     */
    private List<WorkflowNodeEntity> getAnyNodeUnderAllNodeList(List<WorkflowNodeEntity> nodeList, WorkflowNodeEntityExt workflowNodeEntity) {
        String corpid = workflowNodeEntity.getCorpid();
        // 获取当前节点
        List<WorkflowNodeEntity> copyAllList = new ArrayList<>();
        copyAllList.add(workflowNodeEntity);
        // 获取当前节点下面所有的节点
        List<WorkflowNodeEntity> copyList = WorkflowNodeUtil.getAllUnderNodeList(nodeList, workflowNodeEntity.getUid() );
        copyAllList.addAll(copyList);
        // 对条件节点进行重排序以及重命名
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("workflowId", workflowNodeEntity.getWorkflowId());
        param.put("prevId", workflowNodeEntity.getWrapperId());
        param.put("wrapperId", workflowNodeEntity.getWrapperId());
        param.put("type", workflowNodeEntity.getType());
        Integer sort = workflowNodeModel.getEntitysCount(param);
        sort ++;
        workflowNodeEntity.setName(workflowNodeEntity.getName() + StringConstant.UNDER_LINE + I18nMessageUtil.getMessage(CommonConstant.COPY));
        workflowNodeEntity.setPriority(sort);
        long now = DateTimeUtil.getInt();
        copyAllList.forEach(item->{
            item.setId(null);
            item.setUpdateTime(now);
            item.setAddTime(now);
        });
        // 重新对应uid和prev_id、wrapper_id
        Map<String, String> uuidMap = new HashMap<>(copyAllList.size());
        for (WorkflowNodeEntity item : copyAllList) {
            String uuid = UUID.randomUUID().toString();
            uuidMap.put(item.getUid(), uuid);
        }
        for (WorkflowNodeEntity item: copyAllList) {
            item.setUid(uuidMap.get(item.getUid()));
            if (!Objects.equals(item.getPrevId(), workflowNodeEntity.getPrevId())) {
                item.setPrevId(uuidMap.get(item.getPrevId()));
            }
            if (!Objects.equals(item.getWrapperId(), workflowNodeEntity.getWrapperId())) {
                item.setWrapperId(uuidMap.get(item.getWrapperId()));
            }
        }
        return copyAllList;
    }





    @Override
    public WorkflowNodeViewDetailVO viewDetail(WorkflowNodeViewDetailDTO workflowNodeViewDetailDTO) throws XbbException {
        try {
            WorkflowNodeViewDetailVO workflowNodeViewDetailVO = new WorkflowNodeViewDetailVO();
            String corpid = workflowNodeViewDetailDTO.getCorpid();
            Long workflowId = workflowNodeViewDetailDTO.getWorkflowId();
            String prevId = workflowNodeViewDetailDTO.getNodeId();
            List<Integer> nodeList = Arrays.asList(WorkflowNodeTypeEnum.START_NODE.getType(), WorkflowNodeTypeEnum.CREATE_NODE.getType(),
                    WorkflowNodeTypeEnum.SINGLE_DATA_NODE.getType(), WorkflowNodeTypeEnum.UPDATE_NODE.getType());
            List<WorkflowNodeSourceListPojo> sourceList = getNodeList(corpid, prevId, workflowId, nodeList);
            workflowNodeViewDetailVO.setNodeList(sourceList);
            return workflowNodeViewDetailVO;
        } catch (XbbException e) {
            throw e;
        }  catch (Exception e) {
            LOGGER.error("WorkflowNodeServiceImpl.viewDetail error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * 获取节点类型下的节点
     * @param corpid 公司id
     * @param prevId 上一节点的uid
     * @param workflowId 工作流id
     * @param nodeList 节点类型列表
     * @return
     * @throws XbbException
     */
    private List<WorkflowNodeSourceListPojo> getNodeList(String corpid, String prevId, Long workflowId,  List<Integer> nodeList)  throws XbbException{
        List<WorkflowNodeEntity> workflowNodeList = workflowNodeModel.getWorkflowNodeList(corpid, workflowId, " priority " + SortOrder.ASC);

        workflowNodeList = WorkflowNodeUtil.getUpNodeList(workflowNodeList, prevId, nodeList);
        Set<Long> workOrderIdList = new HashSet<>();
        Set<Long> formIdList = new HashSet<>();
        workflowNodeList.forEach(item->{
            if(Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), item.getBusinessType())) {
                workOrderIdList.add(item.getFormId());
            } else {
                formIdList.add(item.getFormId());
            }
        });
        Map<Long, PaasFormEntity> formMap = proFormHelp.getFormMap(formIdList, corpid, DelEnum.NORMAL.getDel());
        Map<Long, WorkOrderFormEntity> workOrderFormMap = proFormHelp.getWorkOrderFormMap(workOrderIdList, corpid, DelEnum.NORMAL.getDel());
        List<WorkflowNodeSourceListPojo> sourceList = new ArrayList<>();
        workflowNodeList.forEach(item->{
            Integer triggerNodeFlag = 0;
            if (Objects.equals(WorkflowNodeTypeEnum.START_NODE.getType(), item.getType())) {
                triggerNodeFlag = 1;
            } else {
                triggerNodeFlag = 0;
            }
            if(Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), item.getBusinessType()) && workOrderFormMap.containsKey(item.getFormId())) {
                WorkflowNodeSourceListPojo workflowNodeSourceListPojo = new WorkflowNodeSourceListPojo(item.getId(), item.getName(),
                        item.getUid(), item.getFormId(), item.getSaasMark(), item.getBusinessType(), workOrderFormMap.get(item.getFormId()).getName(), triggerNodeFlag);
                sourceList.add(workflowNodeSourceListPojo);
            } else if (formMap.containsKey(item.getFormId())) {
                WorkflowNodeSourceListPojo workflowNodeSourceListPojo = new WorkflowNodeSourceListPojo(item.getId(), item.getName(),
                        item.getUid(), item.getFormId(), item.getSaasMark(), item.getBusinessType(), formMap.get(item.getFormId()).getName(), triggerNodeFlag);
                sourceList.add(workflowNodeSourceListPojo);
            }
        });
        return sourceList;
    }

    /**
     * 添加工作流节点
     * @param workflowNodeSaveDTO
     * @return
     * @throws XbbException
     */
    private List<WorkflowNodeEntity> updateWorkflowNode(WorkflowNodeSaveDTO workflowNodeSaveDTO) throws XbbException {
        try {
            String corpid = workflowNodeSaveDTO.getCorpid();
            Long workflowId = workflowNodeSaveDTO.getWorkflowId();
            Long workflowNodeId = workflowNodeSaveDTO.getWorkflowNodeId();
            WorkflowNodeEntity workflowNodeEntity = workflowNodeModel.getByKey(workflowNodeId, corpid);
            if (Objects.isNull(workflowNodeEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260043);
            }
            WorkflowNodePojo workflowNodePojo = workflowNodeSaveDTO.getWorkflowNode();
            // 校验条件节点else属性
            validateElse(workflowNodePojo, corpid, workflowId, workflowNodeId);
            UserVO userVO = workflowNodeSaveDTO.getLoginUser();
            WorkflowNodeEntity updateNode = new WorkflowNodeEntity();
            updateNode.setCorpid(corpid);
            updateNode.setType(workflowNodePojo.getType());
            String workflowNodeName = workflowNodePojo.getName();
            updateNode.setName(workflowNodeName);
            updateNode.setId(workflowNodeId);
            updateNode.setFormId(workflowNodePojo.getFormId());
            updateNode.setAppId(workflowNodePojo.getAppId());
            updateNode.setMenuId(workflowNodePojo.getMenuId());
            updateNode.setSaasMark(workflowNodePojo.getSaasMark());
            updateNode.setBusinessType(workflowNodePojo.getBusinessType());
            updateNode.setConfigData(getConfigData(workflowNodePojo));
            updateNode.setTriggerType(workflowNodeEntity.getTriggerType());
            // 节点校验
            workflowNodeHelp.check(corpid, workflowId, updateNode);
            // 节点更新
            workflowNodeModel.update(updateNode);
            workflowNodeId = updateNode.getId();
            String workflowMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_WORK), userVO.getName(), OperateModuleTypeEnum.WORKFLOW_NODE.getName(), updateNode.getName());
            mongoLogHelp.saveLoggerByInsert(corpid, userVO.getUserId(), userVO.getName(), workflowNodeEntity.getName(), workflowMemo, workflowNodeId.toString(),  workflowNodeSaveDTO.getHttpHeader(), OperateModuleTypeEnum.WORKFLOW_NODE, OperateTypeEnum.EDIT);

            if (Objects.equals(WorkflowNodeTypeEnum.START_NODE.getType(), workflowNodePojo.getType())) {
                WorkflowEntity workflowEntity = new WorkflowEntity();
                Integer usePermission = workflowNodePojo.getUsePermission() == null ? 0 : workflowNodePojo.getUsePermission();
                workflowEntity.setUsePermission(usePermission);
                workflowEntity.setId(workflowNodeSaveDTO.getWorkflowId());
                workflowEntity.setUpdateTime(DateTimeUtil.getInt());
                workflowEntity.setCorpid(corpid);
                workflowEntity.setFormId(workflowNodePojo.getFormId());
                workflowEntity.setAppId(workflowNodePojo.getAppId());
                workflowEntity.setMenuId(workflowNodePojo.getMenuId());
                workflowEntity.setSaasMark(workflowNodePojo.getSaasMark());
                workflowEntity.setBusinessType(workflowNodePojo.getBusinessType());
                Integer type = workflowNodePojo.getCoreConfiguration().getFormTriggerNode().getType();
                workflowEntity.setTriggerEventType(type);
                workflowModel.update(workflowEntity);
            }
            List<WorkflowNodeEntity> workflowNodeList = new ArrayList<>();
            workflowNodeList.add(updateNode);
            return workflowNodeList;
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.updateWorkflowNode error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * 获取这个节点下的全部删除节点
     * @param corpid
     * @param workflowId
     * @param workflowNodeEntity
     * @return
     */
    private Set<Long> getDeleteList(String corpid, Long workflowId, WorkflowNodeEntity workflowNodeEntity) {
        String uid = workflowNodeEntity.getUid();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("workflowId", workflowId);
        List<WorkflowNodeEntity> workflowNodeList = workflowNodeModel.findEntitys(param);
        Set<Long> deleteList = WorkflowNodeUtil.getUnderAllNodeList(workflowNodeList, uid);
        return deleteList;
    }

    /**
     * 获取当前节点下的所有节点，但是不会拿节点下方块节点里的节点，请谨慎使用
     * @param workflowNodeList
     * @param nodeId
     */

    private List<WorkflowNodeEntity> getUnderNodeList(List<WorkflowNodeEntity> workflowNodeList, String nodeId, String wrapperId ) {
        List<WorkflowNodeEntity> underNodeList = new ArrayList<>();
        WorkflowNodeUtil.getUnderNodeList(workflowNodeList,  nodeId, wrapperId, underNodeList);
        return underNodeList;
    }

    /**
     * 创建条件节点
     * @param corpid
     * @param triggerType 表单级触发类型
     * @param workflowId
     * @param workflowNodePojo
     * @param userVO
     * @param httpHeader
     * @param move
     * @param nextWorkflowNodeEntity
     * @return
     */
    private List<WorkflowNodeEntity>  createConditionNode(String corpid, Integer triggerType,  Long workflowId, WorkflowNodePojo workflowNodePojo,
                                                          UserVO userVO, String httpHeader, Integer move, WorkflowNodeEntity nextWorkflowNodeEntity) throws XbbException{
        List<WorkflowNodeEntity> workflowNodeList = new ArrayList<>();
        try {
            Long appId = workflowNodePojo.getAppId();
            Long menuId = workflowNodePojo.getMenuId();
            Long formId = workflowNodePojo.getFormId();
            Integer saasMark = workflowNodePojo.getSaasMark();
            Integer businessType = workflowNodePojo.getBusinessType();
            String prevId = workflowNodePojo.getPrevId();
            // 如果条件块节点为空，且新建的是条件节点，那么需要生成一个条件块节点，两个条件节点
            // 生成块节点uid
            String wrapperNodeUId = UUID.randomUUID().toString();
            List<WorkflowNodeEntity> nodeList = workflowNodeModel.getWorkflowNodeList(corpid, workflowId, null);
            // 查询上一节点
            WorkflowNodeEntity prevNode = workflowNodeModel.getByUId(workflowId, corpid, prevId);
            String wrapperId = null;
            if (Objects.equals(prevNode.getType(), WorkflowNodeTypeEnum.CONDITION_NODE.getType())) {
                // 如果上一节点是条件节点，将条件归类到上一节点中
                wrapperId = prevNode.getWrapperId();
            } else if (StringUtil.isNotEmpty(workflowNodePojo.getWrapperId())) {
                // 如果上一节点的在所属块内，那么当前新加的节点，也应该归属于同一个块
                wrapperId = workflowNodePojo.getWrapperId();
            }
            // 所属哪个块的节点id
            WorkflowNodeCoreConfiguration workflowNodeCoreConfiguration  = new WorkflowNodeCoreConfiguration();
            // 条件块节点
            WorkflowNodeEntity wrapperNode = new WorkflowNodeEntity(corpid, "", triggerType, WorkflowNodeTypeEnum.CONDITION_BLOCK_NODE.getType(), appId, formId, menuId, saasMark, businessType,
                    workflowId, wrapperNodeUId, prevId, wrapperId, null, JSON.toJSONString(workflowNodeCoreConfiguration));
            workflowNodeList.add(wrapperNode);
            WorkflowNodeCoreConfiguration conditionNodeCoreConfiguration = workflowNodePojo.getCoreConfiguration();
            conditionNodeCoreConfiguration.setConditionNode(workflowNodePojo.getCoreConfiguration().getConditionNode());
            // 左边的那个条件节点
            WorkflowNodeEntity leftConditionNodeEntity = new WorkflowNodeEntity(corpid, workflowNodePojo.getName(), triggerType, WorkflowNodeTypeEnum.CONDITION_NODE.getType(), appId, formId, menuId, saasMark, businessType,
                    workflowId, workflowNodePojo.getNodeId(), wrapperNodeUId, wrapperNodeUId, 1, getConfigData(workflowNodePojo), null);
            workflowNodeList.add(leftConditionNodeEntity);
            // 右节点uid标识
            String uuId = UUID.randomUUID().toString();
            ConditionNode conditionNode = new ConditionNode();
            String name;
            if (Objects.equals(conditionNodeCoreConfiguration.getConditionNode().getType(), ConditionTypeEnum.GENERAL_CONDITION.getType())) {
                // 右边的条件节点
                conditionNode.setConditions(new WorkflowJointConditionPojo());
                conditionNode.setConditionType(WorkflowNodeConditionTypeEnum.NORMAL_TYPE.getType());
                conditionNode.setEditedData(BasicConstant.ONE);
                name = CONDITION_NODE_NAME;
            } else if (Objects.equals(conditionNodeCoreConfiguration.getConditionNode().getType(), ConditionTypeEnum.APPROVAL_RESULT_CONDITION.getType())) {
                conditionNode.setConditions(new WorkflowJointConditionPojo());
                conditionNode.setConditionType(WorkflowNodeConditionTypeEnum.APPROVAL_REFUSE.getType());
                conditionNode.setType(ConditionTypeEnum.APPROVAL_RESULT_CONDITION.getType());
                name = APPROVAL_REFUSE_RESULT_CONDITION_NODE_NAME;
            } else {
                // 右边的条件节点
                conditionNode.setConditions(new WorkflowJointConditionPojo());
                conditionNode.setConditionType(WorkflowNodeConditionTypeEnum.NONE_DATA.getType());
                conditionNode.setType(ConditionTypeEnum.RESULT_CONDITION.getType());
                name = NONE_RESULT_CONDITION_NODE_NAME;
            }
            WorkflowNodeEntity rightNode = new WorkflowNodeEntity(corpid, I18nMessageUtil.getMessage(name), triggerType, WorkflowNodeTypeEnum.CONDITION_NODE.getType(), appId, formId, menuId, saasMark, businessType,
                    workflowId, uuId, wrapperNodeUId, wrapperNodeUId, 2, JSON.toJSONString(conditionNode));
            workflowNodeList.add(rightNode);
            workflowNodeModel.insertBatch(workflowNodeList);
            // 更新下一个节点的信息
            updatePreNode(nextWorkflowNodeEntity, move, corpid, workflowId, wrapperNodeUId, uuId, workflowNodePojo, nodeList);
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.createConditionNode error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        return workflowNodeList;
    }

    /**
     * 更新下一个节点的prevId
     * @param nextWorkflowNodeEntity 下一个节点
     * @param move 左移；右移；不移动
     * @param corpid 公司id
     * @param workflowId 节点id
     * @param wrapperUUId 条件块id
     * @param uuId 右节点uid标识
     * @param workflowNodePojo
     */
    private void updatePreNode(WorkflowNodeEntity nextWorkflowNodeEntity, Integer move, String corpid, Long workflowId,
                               String wrapperUUId, String uuId, WorkflowNodePojo workflowNodePojo, List<WorkflowNodeEntity> workflowNodeList) {
        if (Objects.nonNull(nextWorkflowNodeEntity)) {
            WorkflowNodeEntity updateWorkflowNode = new WorkflowNodeEntity();
            updateWorkflowNode.setId(nextWorkflowNodeEntity.getId());
            updateWorkflowNode.setCorpid(corpid);
            updateWorkflowNode.setUpdateTime(DateTimeUtil.getInt());
            List<WorkflowNodeEntity> underNodeList = new ArrayList<>();
            String prevId = null;
            if (Objects.equals(BasicConstant.ZERO, move)) {
                // 节点不移动 更新下一节点的上一节点标识
                updateWorkflowNode.setPrevId(wrapperUUId);
                workflowNodeModel.update(updateWorkflowNode);
                return;
            }
            if (Objects.equals(BasicConstant.ONE, move)) {
                // 节点左移动，需要把下方的所有节点都移动到左边
                underNodeList = getUnderNodeList(workflowNodeList, workflowNodePojo.getPrevId(), workflowNodePojo.getWrapperId());
                prevId = workflowNodePojo.getNodeId();
                updateWorkflowNode.setPrevId(prevId);
            } else {
                // 节点右移动，需要把下方的所有节点都移动到右边
                underNodeList = getUnderNodeList(workflowNodeList, workflowNodePojo.getPrevId(), workflowNodePojo.getWrapperId());
                updateWorkflowNode.setWrapperId(wrapperUUId);
                updateWorkflowNode.setPrevId(uuId);
            }
            if (CollectionsUtil.isNotEmpty(underNodeList)) {
                List<WorkflowNodeEntity> updateList = new ArrayList<>();
                underNodeList.forEach(item->{
                    WorkflowNodeEntity entity = new WorkflowNodeEntity();
                    entity.setId(item.getId());
                    entity.setWrapperId(wrapperUUId);
                    entity.setUpdateTime(DateTimeUtil.getInt());
                    updateList.add(entity);
                });
                workflowNodeModel.updateWrapperId(updateList, corpid);
            }
            workflowNodeModel.update(updateWorkflowNode);
        }
    }

    /**
     * 根据prevId获取下一个节点，可能会拿不到
     * @param workflowId
     * @param uid
     * @param corpid
     * @return
     */
    private WorkflowNodeEntity getNextNode(Long workflowId, String uid, String corpid) {
        WorkflowNodeEntity nextWorkflowNodeEntity = null;
        List<WorkflowNodeEntity> nodeList =  workflowNodeModel.getByWorkflowIdAndPrevId(workflowId, uid, corpid);
        if (CollectionUtils.isNotEmpty(nodeList)) {
            if (nodeList.size()> BasicConstant.ONE) {
                for (WorkflowNodeEntity item : nodeList) {
                    if (!Objects.equals(item.getType(), WorkflowNodeTypeEnum.CONDITION_NODE.getType())) {
                        nextWorkflowNodeEntity = item;
                        break;
                    }
                }
            } else {
                nextWorkflowNodeEntity = nodeList.get(0);
            }
        }
        return nextWorkflowNodeEntity;
    }

    /**
     * 在添加和删除节点时，返回节点数
     * @param corpid
     * @param workflowId
     * @return
     * @throws XbbException
     */
    private WorkflowNodeTreePojo getNodeTree(String corpid, Long workflowId) throws XbbException {
        List<WorkflowNodeEntity> nodeList = workflowNodeModel.getWorkflowNodeList(corpid, workflowId, " priority " + SortOrder.ASC);
        WorkflowGetPojo workflowGetPojo = workflowNodeHelp.getContent(nodeList, corpid);
        List<WorkflowNodeTreePojo> workflowNodeTreeList = workflowNodeHelp.getNodeList(nodeList, workflowGetPojo);
        WorkflowNodeTreePojo workflowNodeTreePojo = WorkflowNodeUtil.buildTree(workflowNodeTreeList);
        return workflowNodeTreePojo;
    }

    /**
     * 同级条件分支只允许一个else条件节点
     * @param workflowNodePojo 节点属性
     * @param corpid 公司id
     * @param workflowId 工作流id
     * @param workflowNodeId 当前保存的节点id
     * @throws XbbException
     */
    private void validateElse(WorkflowNodePojo workflowNodePojo, String corpid, Long workflowId, Long workflowNodeId) throws XbbException {
        if (Objects.equals(workflowNodePojo.getType(), WorkflowNodeTypeEnum.CONDITION_NODE.getType())) {
            ConditionNode updateConditionNode = workflowNodePojo.getCoreConfiguration().getConditionNode();
            if (Objects.nonNull(updateConditionNode) && Objects.equals(updateConditionNode.getConditionType(), WorkflowNodeConditionTypeEnum.ELSE_TYPE.getType())) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID, corpid);
                param.put(StringConstant.DEL, DelEnum.NORMAL);
                param.put("workflowId", workflowId);
                param.put("prevId", workflowNodePojo.getPrevId());
                param.put("type", WorkflowNodeTypeEnum.CONDITION_NODE.getType());
                List<WorkflowNodeEntity> list = workflowNodeModel.findEntitys(param);
                for (WorkflowNodeEntity item : list) {
                    if (!Objects.equals(item.getId(), workflowNodeId) && Objects.equals(WorkflowNodeTypeEnum.CONDITION_NODE.getType(), item.getType())) {
                        ConditionNode conditionNode = JSON.parseObject(item.getConfigData(), ConditionNode.class);
                        if (Objects.equals(conditionNode.getConditionType(), WorkflowNodeConditionTypeEnum.ELSE_TYPE.getType())) {
                            throw new XbbException(ProErrorCodeEnum.API_ERROR_260048);
                        }
                    }
                }
            }
        }
    }
}
